package cn.com.acca.ma.dao.impl;

import cn.com.acca.ma.dao.Robot5StockTransactRecordDao;
import cn.com.acca.ma.model.Robot5StockTransactRecord;
import cn.com.acca.ma.pojo.BuySuggestion;
import cn.com.acca.ma.pojo.ProfitAndLossRate;
import cn.com.acca.ma.pojo.SellSuggestion;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Robot5StockTransactRecordDaoImpl extends BaseDaoImpl<Robot5StockTransactRecord> implements
        Robot5StockTransactRecordDao {

    public Robot5StockTransactRecordDaoImpl() {
        super();
    }

    /**
     * 卖股票/买股票
     * @param sellDate
     * @param mandatoryStopLoss
     * @param mandatoryStopLossRate
     * @param mandatoryStopProfit
     * @param mandatoryStopProfitRate
     */
    @Override
    public void sellOrBuy(String sellDate, Integer mandatoryStopLoss, Double mandatoryStopLossRate, Integer mandatoryStopProfit, Double mandatoryStopProfitRate) {
        logger.info("卖股票/买股票");

        String sql = "{call PKG_ROBOT5.sell_or_buy('" + sellDate + "', " + mandatoryStopLoss + ", "
                + mandatoryStopLossRate + ", " + mandatoryStopProfit + ", " + mandatoryStopProfitRate + ")}";

        doSQLInTransaction(sql);
    }

    /**
     * 买股票/卖股票。同时用于做多和做空
     * @param buyDate
     * @param weekOrBool
     * @param thisMethodHoldStockNumber
     * @param holdStockNumber
     */
    @Override
    public void buyOrSell(String buyDate, Integer weekOrBool, Integer thisMethodHoldStockNumber, Integer holdStockNumber) {
        logger.info("买股票/卖股票，日期为【" + buyDate + "】，算法为【" + weekOrBool + "】，" +
                "总共持股数量为【" + holdStockNumber + "】，这个算法的持股数量为【" + thisMethodHoldStockNumber + "】");

        // 存储过程最后的参数-1其实没有意义，不用管
        String sql = "{call PKG_ROBOT5.buy_or_sell('" + buyDate + "', " + weekOrBool + ", " + thisMethodHoldStockNumber +
                ", " + holdStockNumber + ")}";

        doSQLInTransaction(sql);
    }

    /**
     * 获取买入建议列表
     * 用于做多
     * @param buyDate
     * @return
     */
    public List<Robot5StockTransactRecord> getBullRobotStockTransactRecordListForBuy(String buyDate) {
        logger.info("获取买入建议列表，日期【" + buyDate + "】，用于做多");

        String sql = "select * from robot5_stock_transact_record t "
                + "where t.buy_date=to_date(:buyDate,'yyyy-mm-dd') "
                + "and t.sell_date is null and t.sell_price is null and t.sell_amount is null "
                + "and t.direction=1";
        Map map = new HashMap();
        map.put("buyDate", buyDate);

        return (List<Robot5StockTransactRecord>)doSQLQueryInTransaction(sql, map, Robot5StockTransactRecord.class);
    }

    /**
     * 获取卖出建议列表
     * 用于做多
     * @param sellDate
     * @return
     */
    public List<Robot5StockTransactRecord> getBullRobotStockTransactRecordListForSell(String sellDate) {
        logger.info("获取卖出建议列表，日期【" + sellDate + "】，用于做多");

        String sql = "select * from robot5_stock_transact_record t "
                + "where t.sell_date=to_date(:sellDate,'yyyy-mm-dd') "
                + "and t.sell_date is not null and t.sell_price is not null and t.sell_amount is not null "
                + "and t.direction=1";
        Map map = new HashMap();
        map.put("sellDate", sellDate);

        return (List<Robot5StockTransactRecord>)doSQLQueryInTransaction(sql, map, Robot5StockTransactRecord.class);
    }

    /**
     * 获取卖出建议列表
     * 用于做空
     * @param sellDate
     * @return
     */
    public List<Robot5StockTransactRecord> getShortRobotStockTransactRecordListForSell(String sellDate) {
        logger.info("获取卖出建议列表，日期【" + sellDate + "】，用于做空");

        String sql = "select * from robot5_stock_transact_record t "
                + "where t.sell_date=to_date(:sellDate,'yyyy-mm-dd') "
                + "and t.buy_date is null and t.buy_price is null and t.buy_amount is null "
                + "and t.direction=-1";
        Map map = new HashMap();
        map.put("sellDate", sellDate);

        return (List<Robot5StockTransactRecord>)doSQLQueryInTransaction(sql, map, Robot5StockTransactRecord.class);
    }

    /**
     * 获取买入建议列表
     * 用于做空
     * @param buyDate
     * @return
     */
    public List<Robot5StockTransactRecord> getShortRobotStockTransactRecordListForBuy(String buyDate) {
        logger.info("获取买入建议列表，日期【" + buyDate + "】，用于做空");

        String sql = "select * from robot5_stock_transact_record t "
                + "where t.buy_date=to_date(:buyDate,'yyyy-mm-dd') "
                + "and t.buy_date is not null and t.buy_price is not null and t.buy_amount is not null "
                + "and t.direction=-1";
        Map map = new HashMap();
        map.put("buyDate", buyDate);

        return (List<Robot5StockTransactRecord>)doSQLQueryInTransaction(sql, map, Robot5StockTransactRecord.class);
    }

    /**
     * 获取卖出建议列表
     * @param sellDate
     * @return
     */
    public List<SellSuggestion> getSellSuggestionList_multipleMethod(String sellDate){
        logger.info("获取卖出建议列表，日期【" + sellDate + "】");

        String sql = "select rstr.stock_code stockCode, si_.name_ stockName, rstr.sell_date sellDate, "
                + "rstr.sell_price sellPrice, rstr.sell_amount sellAmount, rstr.filter_type filterType, rstr.direction direction "
                + "from robot5_stock_transact_record rstr "
                + "join stock_info si_ on si_.code_=rstr.stock_code "
                + "where rstr.sell_date=to_date(:sellDate,'yyyy-mm-dd') "
                + "and (rstr.sell_date is not null and rstr.sell_price is not null and rstr.sell_amount is not null and rstr.direction=1) "
                + "or (rstr.buy_date is null and rstr.buy_price is null and rstr.buy_amount is null and rstr.direction=-1)";
        Map map = new HashMap();
        map.put("sellDate", sellDate);

        return (List<SellSuggestion>)doSQLQueryInTransaction(sql, map, SellSuggestion.class);
    }

    /**
     * 获取买入建议列表
     * @param buyDate
     * @return
     */
    public List<BuySuggestion> getBuySuggestionList_multipleMethod(String buyDate) {
        logger.info("获取买入建议列表，日期【" + buyDate + "】");

        String sql = "select rstr.stock_code stockCode, si_.name_ stockName, rstr.buy_date buyDate, "
                + "rstr.buy_price buyPrice, rstr.buy_amount buyAmount, rstr.filter_type filterType, rstr.direction direction "
                + "from robot5_stock_transact_record rstr "
                + "join stock_info si_ on si_.code_=rstr.stock_code "
                + "where rstr.buy_date=to_date(:buyDate,'yyyy-mm-dd') "
                + "and (rstr.sell_date is null and rstr.sell_price is null and rstr.sell_amount is null and rstr.direction=1)"
                + "or (rstr.buy_date is not null and rstr.buy_price is not null and rstr.buy_amount is not null and rstr.direction=-1)";
        Map map = new HashMap();
        map.put("buyDate", buyDate);

        return (List<BuySuggestion>)doSQLQueryInTransaction(sql, map, BuySuggestion.class);
    }

    /**
     * 计算最近三个月，Robot3Main和Robot4Main的收益率的总和
     * @param currentDate
     * @return 
     */
    @Override
    public ProfitAndLossRate sumRobot3MainAndRobot4MainWithinLastThreeMonth(String currentDate) {
        logger.info("计算Robot3Main和Robot4Main的收益率的总和");

        String sql = "select "
                + "(select sum(t1.profit_and_loss_rate) from robot5_stock_transact_record t1 where (case when t1.direction=1 then t1.buy_date when t1.direction=-1 then t1.sell_date end) between add_months(to_date(:currentDate, 'yyyy-mm-dd'),-3) and to_date(:currentDate, 'yyyy-mm-dd') and t1.filter_type between 1 and 8) robot4MainProfitAndLossRate, "
                + "(select sum(t2.profit_and_loss_rate) from robot5_stock_transact_record t2 where (case when t2.direction=1 then t2.buy_date when t2.direction=-1 then t2.sell_date end) between add_months(to_date(:currentDate, 'yyyy-mm-dd'),-3) and to_date(:currentDate, 'yyyy-mm-dd') and t2.filter_type between 9 and 10) robot3MainProfitAndLossRate "
                + "from dual";
        Map map = new HashMap();
        map.put("currentDate", currentDate);
        List list = doSQLQueryInTransaction(sql, map, ProfitAndLossRate.class);
        if (null == list || list.size() == 0) {
            return null;
        } else {
            return (ProfitAndLossRate) list.get(0);
        }
    }

}
